from typing import List, Optional
from sqlalchemy.orm import Session

from app.models.role import Role
from app.models.user import User
from app.exception import ResourceNotFoundError, ValidationError
from app.utils.pagination import paginate

class RoleService:
    """角色服务类"""
    
    @staticmethod
    def create_role(db: Session, name: str, code: str, description: Optional[str] = None) -> Role:
        """创建角色
        
        Args:
            db: 数据库会话
            name: 角色名称
            code: 角色编码
            description: 角色描述
            
        Returns:
            Role: 创建的角色对象
            
        Raises:
            ValidationError: 角色名称或编码已存在
        """
        # 检查角色名称和编码是否已存在
        if db.query(Role).filter(Role.name == name).first():
            raise ValidationError(f"角色名称 {name} 已被使用")
        if db.query(Role).filter(Role.code == code).first():
            raise ValidationError(f"角色编码 {code} 已被使用")
        
        # 创建角色
        role = Role(name=name, code=code, description=description)
        db.add(role)
        db.commit()
        db.refresh(role)
        return role
    
    @staticmethod
    def get_role_by_id(db: Session, role_id: int) -> Role:
        """通过ID获取角色
        
        Args:
            db: 数据库会话
            role_id: 角色ID
            
        Returns:
            Role: 角色对象
            
        Raises:
            ResourceNotFoundError: 角色不存在
        """
        role = db.query(Role).filter(Role.id == role_id).first()
        if not role:
            raise ResourceNotFoundError(f"ID为 {role_id} 的角色不存在")
        return role
    
    @staticmethod
    def get_role_by_code(db: Session, code: str) -> Optional[Role]:
        """通过角色编码获取角色
        
        Args:
            db: 数据库会话
            code: 角色编码
            
        Returns:
            Optional[Role]: 角色对象，不存在则返回None
        """
        return db.query(Role).filter(Role.code == code).first()
    
    @staticmethod
    def get_role_list(db: Session, page: int = 1, page_size: int = 10) -> dict:
        """获取角色列表（分页）
        
        Args:
            db: 数据库会话
            page: 页码
            page_size: 每页大小
            
        Returns:
            dict: 分页结果
        """
        roles = db.query(Role).all()
        return paginate(roles, page, page_size)
    
    @staticmethod
    def update_role(db: Session, role_id: int, **kwargs) -> Role:
        """更新角色信息
        
        Args:
            db: 数据库会话
            role_id: 角色ID
            **kwargs: 要更新的字段
            
        Returns:
            Role: 更新后的角色对象
            
        Raises:
            ResourceNotFoundError: 角色不存在
            ValidationError: 角色名称或编码已被其他角色使用
        """
        role = RoleService.get_role_by_id(db, role_id)
        
        # 检查角色名称和编码是否已被其他角色使用
        if 'name' in kwargs and kwargs['name'] != role.name:
            if db.query(Role).filter(Role.name == kwargs['name']).first():
                raise ValidationError(f"角色名称 {kwargs['name']} 已被使用")
                
        if 'code' in kwargs and kwargs['code'] != role.code:
            if db.query(Role).filter(Role.code == kwargs['code']).first():
                raise ValidationError(f"角色编码 {kwargs['code']} 已被使用")
        
        # 更新角色信息
        for key, value in kwargs.items():
            if hasattr(role, key):
                setattr(role, key, value)
        
        db.commit()
        db.refresh(role)
        return role
    
    @staticmethod
    def delete_role(db: Session, role_id: int) -> bool:
        """删除角色
        
        Args:
            db: 数据库会话
            role_id: 角色ID
            
        Returns:
            bool: 是否删除成功
            
        Raises:
            ResourceNotFoundError: 角色不存在
        """
        role = RoleService.get_role_by_id(db, role_id)
        db.delete(role)
        db.commit()
        return True
    
    @staticmethod
    def assign_role_to_user(db: Session, user_id: int, role_id: int) -> User:
        """给用户分配角色
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            role_id: 角色ID
            
        Returns:
            User: 更新后的用户对象
            
        Raises:
            ResourceNotFoundError: 用户或角色不存在
        """
        from app.services.user_service import UserService
        
        user = UserService.get_user_by_id(db, user_id)
        role = RoleService.get_role_by_id(db, role_id)
        
        # 检查用户是否已经拥有该角色
        if role in user.roles:
            return user
        
        # 给用户添加角色
        user.roles.append(role)
        db.commit()
        db.refresh(user)
        return user
    
    @staticmethod
    def remove_role_from_user(db: Session, user_id: int, role_id: int) -> User:
        """从用户中移除角色
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            role_id: 角色ID
            
        Returns:
            User: 更新后的用户对象
            
        Raises:
            ResourceNotFoundError: 用户或角色不存在
        """
        from app.services.user_service import UserService
        
        user = UserService.get_user_by_id(db, user_id)
        role = RoleService.get_role_by_id(db, role_id)
        
        # 检查用户是否拥有该角色
        if role not in user.roles:
            raise ResourceNotFoundError(f"用户 {user_id} 没有分配角色 {role_id}")
        
        # 从用户中移除角色
        user.roles.remove(role)
        db.commit()
        db.refresh(user)
        return user
    
    @staticmethod
    def get_user_roles(db: Session, user_id: int) -> List[Role]:
        """获取用户拥有的角色列表
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            
        Returns:
            List[Role]: 角色列表
            
        Raises:
            ResourceNotFoundError: 用户不存在
        """
        from app.services.user_service import UserService
        
        user = UserService.get_user_by_id(db, user_id)
        return user.roles
